package it.gtd.swimpool.model.entity;

import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;

import javax.persistence.*;
import java.io.Serializable;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

@Entity
@Table(name = "skills")
@NamedQueries({
        @NamedQuery(name = "Skill.byName",
                query = "SELECT skill FROM Skill AS skill WHERE skill.name = :name"),
        @NamedQuery(name = "Skill.proposals",
                query = "SELECT skill FROM Skill AS skill WHERE skill.approver IS NULL"),
        @NamedQuery(name = "Skill.all",
                query = "SELECT skill FROM Skill AS skill WHERE skill.approver IS NOT NULL")
})
@Beta
public class Skill implements Serializable {
    @Id
    @GeneratedValue
    private int id;

    @Column(unique = true, nullable = false)
    private String name;
    @VisibleForTesting
    static final int MAX_NAME_LENGTH = 30;
    @VisibleForTesting
    static final int MIN_NAME_LENGTH = 5;

    @Basic(optional = true)
    private String description;
    @VisibleForTesting
    static final int MAX_DESCRIPTION_LENGTH = 255;

    @ManyToOne
    private User proposer;

    @ManyToOne(optional = true)
    private Administrator approver;

    public Skill() {
    }

    public Skill(String name, User proposer) {
        this();

        checkNotNull(name, "name can't be null");
        checkNotNull(proposer, "proposer can't be null");

        this.name = name;
        this.proposer = proposer;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        checkNotNull(name, "name can't be null");
        checkArgument(!name.isEmpty(), "Skill name can't be empty");
        checkArgument(name.length() > MIN_NAME_LENGTH, "Skill name length must be bigger then " + MIN_NAME_LENGTH);
        checkArgument(name.length() < MAX_NAME_LENGTH, "Skill name length can't be bigger then " + MAX_NAME_LENGTH);

        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        checkNotNull(description, "description can't be null");
        checkArgument(!description.isEmpty(), "Description can't be empty");
        checkArgument(description.length() < MAX_DESCRIPTION_LENGTH, "Skill description length can't be bigger then " + MAX_DESCRIPTION_LENGTH);

        this.description = description;
    }

    public User getProposer() {
        return proposer;
    }

    public void setProposer(User proposer) {
        checkNotNull(proposer, "proposer can't be null");

        this.proposer = proposer;
    }

    public boolean isApproved() {
        return this.approver != null;
    }

    public Administrator getApprover() {
        return approver;
    }

    public void setApprover(Administrator approver) {
        checkNotNull(approver, "approver can't be null");

        this.approver = approver;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Skill)) return false;

        Skill skill = (Skill) o;

        if (!name.equals(skill.name)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }

}
